<!DOCTYPE html>
<html>
<head>
	<title>Meteoritos</title>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8" >
	<link rel="stylesheet" href="css/style.css" />
 <link rel="stylesheet" href="css/leaflet.css" />
 <link rel="stylesheet" href="css/dc.css" />
	<link rel="stylesheet" href="css/MarkerCluster.css" />
	<link rel="stylesheet" href="css/MarkerCluster.Default.css" />
	<!--<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />-->
</head>

<body>
	<script type="text/javascript" src="js/leaflet.js"></script>
	<script type="text/javascript" src="js/d3.js"></script>
	<script type="text/javascript" src="js/crossfilter.js"></script>
	<script type="text/javascript" src="js/dc.js"></script>
	<script type="text/javascript" src="js/colorbrewer.js"></script>
	<script type="text/javascript" src="js/leaflet.markercluster-src.js"></script>


	<div id="conteiner">
	
	<div class="row">
			<h3>Disciplina de Visualização Científica<br>UFC 2013.2<br>Ciência da Computação</h3>
			<h4><a href="javascript:dc.filterAll(); dc.renderAll();">Limpar tudo</a></h4>
	</div>
	
	<div class="column_left">

	<div class="row">
			<h1>Informações</h1>
			<p>
					Os dados utilizados neste trabalho foram disponibilizados em: 
					<a target="_blank" href="http://visualizing.org/datasets/meteorite-landings/">Visualizing.org</a>.
					Para acompanhar como foi a evolução deste trabalho, o código fonte está disponível em: 
					<a target="_blank" href="http://code.google.com/p/meteorite-project/">Google Codes</a>.
					Fora utilizadas as bibliotecas em javascript: 
					<a target="_blank" href="xxx">Leaflet</a>, para o mapa; 
					<a target="_blank" href="xxx">d3</a> para renderizar os gráficos em svg;
					<a target="_blank" href="xxx">Crossfilter</a> e 
					<a target="_blank" href="xxx">dc</a>, para deixar os gráficos dinâmicos; 
					<a target="_blank" href="xxx">OpenLayers</a>, para calcular a localização dos meteoritos.
			</p>
			<h1>Sobre os meteorítos</h1>
			<p>
					No mapa pode ser visto os pontos onde os meteoritos cairam 
					e em cada um desses pontos têm todas as informaçãos disponibilizadas sobre cada meteorito, 
					que são: nome, coordenadas, ano que caiu, massa, país onde caiu, material, 
					se foi ou não encontrada, e se o material ainda existe por causa do clima da terra. 
			</p>
			<h2>Conclusões</h2>
			<p>
					 Por existirem 3 meteoritos em anos a.C, o histograma começa na data de -2500. 
					 Entretanto, os meteoritos forma mais reportados depois do ano de 1900. 
					 Também existem alguns que não estão datados, que foi definido para se localizar no final do histograma, 
					 todos esses foram achados.  
			</p>
			<p>
					Quanto ao material, a grande maioria é derivada do aço. 
					Existem poucas "relíquias", tanto que mal aparecem no grafico. A maior parte de todos os meteorítos foi achada, 
					e existiram alguns picos altos que indicam que possuiram grandes massas. 
					Infelizmente não se sabe se o fato de possuir grande massa influenciava no tamanho o objeto, como no caso de Chelyabinsk.
					A queda desse meteoro, em 2013, foi bastante falada, porque foi um fenomeno que chamou bastante atenção. 
					O meteoro era grande, e se transformou em uma bola de fogo quando entrou na atmosfera. 
					Como forma de comparação, a bomba nuclear de Hiroshima liberou cerca de 13 quilotons de energia, enquanto esse meteoro liberou 500 quilotons.
					Porem, como pode-se ver, não houve nenhum pico muito alto em 2013, isso é, ja cairam meteoros com uma massa maior que esse. 
			</p>
			
			<p>
					A maior parte dos meteoritos caiu na Antartica, alguns cairam na água, e muitos não se possui a localização exata.
					Alguns países como a Líbia e Omã, possuem muitos indícios de queda, a maioria no intervalo de tempo de 1994 a 2011,
					os Estados Unidos também posuiem uma grande quantidade de meteoritos reportados. 
					Porém, fica a dúvida, esses lugares possuem mais probabilidade de cair meteoritos, 
					ou existem mis estudiosos que reportam com precisão todas as quedas?  
			</p>
	</div>	
	
		<h2>Mapa</h2>
		<div id="map"></div>

		<h2>Histograma dos meteorítos caidos</h2>
		<div id="year-chart" class="chart">
			<span class="reset" style="display: none;">Intervalo: <span class="filter"></span></span>
			<a class="reset" href="javascript:yearChart.filterAll();dc.redrawAll();" style="display: none;">limpar</a>

			<div class="clearfix"></div>
		</div>
		
		<h2>Gráfico da soma das massas nos anos</h2>
		<div id="mass-chart" class="chart">
			<span class="reset" style="display: none;">Intervalo: <span class="filter"></span></span>
			<a class="reset" href="javascript:massChart.filterAll();dc.redrawAll();" style="display: none;">limpar</a>

			<div class="clearfix"></div>
		</div>

	</div>
 
		
	<div class="column_right">
		<h2>Gráfico do tipo<br>do material pela massa</h2>
		<div id="type-chart" class="chart">
			<span class="reset" style="display: none;">Intervalo: <span class="filter"></span></span>
			<a class="reset" href="javascript:typeChart.filterAll();dc.redrawAll();" style="display: none;">limpar</a>

			<div class="clearfix"></div>
		</div>
	</div>
 
		
	<div class="column_right">
		<h2>Gráfico dos meteorítos que cairam em cada país</h2>
		<div id="country-chart" class="chart">
			<span class="reset" style="display: none;">Intervalo: <span class="filter"></span></span>
			<a class="reset" href="javascript:countryChart.filterAll();dc.redrawAll();" style="display: none;">limpar</a>

			<div class="clearfix"></div>
		</div>
		
	</div>
		
	<div class="row">
    <br>
			<h1>Detalhes de implementação</h1>
			<h2>Dados</h2>
			<p>
					Os dados continham algumas informações faltando, com isso forma tomadas algumas decisões discutidas a seguir. 
					Para o mapa, essas informações são exibidas como "-". 
					Nos gráficos, a massa não é somada, e os anos indefinidos forma todos colocados como 2080. 
					Os materiais possuiem uma grande variação, por exemplo: "Iron, IAB-sHL", "Iron, IIIAB-an", "Iron, IAB complex" etc,  
					que foram tratados no gráfico somente como "Iron".
			</p>
			
			<h2>Países</h2>
			<p>
					Para calcular o país em que o meteorito caiu,  
					foi feito um <a target="_blank" href="preprocessing.html">pré-processamento</a> 
					no arquivo para incluir a localização. Quando não caia em nenhum dos paises, foi adicionado uma resposta de
					"caiu na água", e se não possuir nenhum valor de latitude ou longitude, foi classificado como "inválido".
			</p>
			
			<h2>Marcadores do mapa</h2>
			<p>
					Como se trata de muitos marcadores, foi utilizado uma biblioteca de clusters de marcadores. 
					Caso isso não fosse includo, ficaria invíavel a visualização de tão lenta.
			</p>
			
			<h2>"Trabalhos futuros"</h2>
			<p>
					Existem maneiras de trabalhar com a interação dos gráficos com o mapa, porém isso não foi implementado. 
					Isso pode ser visto em: 
					<a target="_blank" href="http://threatwiki.thesentinelproject.org/iranvisualization">Iran Visualization</a>. 
					Também existe uma biblioteca que faz isso automaticamente 
					<a target="_blank" href="http://sztanko.github.io/crosslet/">Crosslet</a>. 
			</p>		
					 
	</div>	
		
		<!--
		<div id="type-chart" class="chart">
			<span class="reset" style="display: none;">Intervalo: <span class="filter"></span></span>
			<a class="reset" href="javascript:latlongChart.filterAll();dc.redrawAll();" style="display: none;">limpar</a>

			<div class="clearfix"></div>
		</div>
		-->

	</div>
	
	<script type="text/javascript">
	
		// variaveis iniciais---------------------------------------------
		// criando o mapa
		/* ----------------------- MAPA------------------------ */
		var map = L.map('map').setView([0, 0], 2);

		L.tileLayer('http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png', {
		    key: 'b31899c45e1b4970a918e93e65bb82c0',
		    styleId: 31408,
		    maxZoom: 18
		}).addTo(map);
		
		
		
		// grafico de ano
		var yearChart = dc.barChart("#year-chart");
		var massChart = dc.compositeChart("#mass-chart"); //lineChart("#mass-chart")
		var countryChart = dc.rowChart("#country-chart");
		var typeChart = dc.rowChart("#type-chart");
		//var latLongChart = dc.bubbleChart("#latlong-chart");
		//var typeChart = dc.bubbleChart("#type-chart");
		
		
		
		// funções--------------------------------------------------------
		
		function founded(b) {
			if(b == "Found") {return "Sim"}
			else if(b == "Fell") {return "Não"}
			else {return "-"}
		}
		
		function relict(b) {
			if(b == "Relict") {return "Sim"}
			else if(b == "Valid") {return "Não"}
			else {return "-"}
		}
		
		function radius(mass) {
			if (mass < 0) return 3;
			return (32 * mass)/(60000000) + 3; 
			// x = ((25 - 3) y) / (60000000)+3
		}
		
		function isInvalidNumberYear(n) {
			if (n == 2080) return "-";
			return n;
		}
		
		function setInvalidNumberYear(n) {
			if (n == "") return +2080;
			return +n;
		}
		
		function isInvalidNumberMass(n) {
			if (n == -1) return "-";
			return n + "g";
		}
		
		function setInvalidNumberMass(n) {
			if (n == "") return -1;
			return +n;
		}
		
		function setInvalidCoordinates(n, m) {
			if (n == "" | m == "") return true;
			return false;
		}
		
		function isInvalidCoordinates(g) {
			if (g.invalidCoordinates) return "-, -";
			return g.coordinates[0] + ", " + g.coordinates[1];
		}
			
		
		
		
		// colocando para o conteudo aparecer-----------------------------
		
		var geojson;
		
		function onEachFeature(feature, layer) {
			var popupContent = "<div id=\"info\">";
			
			popupContent += "<h3>Nome [" + isInvalidCoordinates(feature.geometry) + "]</h3><h1>" + feature.properties.name + "</h1><hr>";
			popupContent += "<div id=\"info\" class=\"left\">";
			popupContent += "<h3>Ano</h3><h4>" + isInvalidNumberYear(feature.properties.year) + "</h4>";
			popupContent += "<h3>Massa</h3><h4>" + isInvalidNumberMass(feature.properties.mass) + "</h4>";
			popupContent += "</div>";
			popupContent += "<div id=\"info\" class=\"right\">";
			popupContent += "<h3>Encontrada</h3><h4>" + founded(feature.properties.fall) + "</h4>";
			popupContent += "<h3>Relíquia</h3><h4>" + relict(feature.properties.valid) + "</h4>";
			popupContent += "</div>";
			popupContent += "<div id=\"info\" class=\"bottom\">";
			popupContent += "<h3>País</h3><h4>" + feature.properties.country + "</h4>";
			popupContent += "<h3>Tipo</h3><h4>" + feature.properties.type + "</h4>";
			popupContent += "</div><div class=\"clear\"></div>";
			
			popupContent += "</div>";

			layer.bindPopup(popupContent);
		}




		// lendo dados----------------------------------------------------
		
		d3.csv("data/meteoritestest.csv", function(data) {
    //var i = 0;
    var dataSet = data.map(function(d){
    		/*if(d.year < 0)
    			console.log("AQUI! ", i++, "     ", d.id);*/
  				return {
            type: "Feature",
            geometry: {
                type: "Point",
                invalidCoordinates: setInvalidCoordinates(d.reclong, d.reclat),
                coordinates: [+d.reclong, +d.reclat]
            },
            properties: {
                year: setInvalidNumberYear(d.year),
                fall: d.fall,
                mass: setInvalidNumberMass(d.mass),
                type: d.recclass,
                valid: d.nametype,
                name: d.name,
                country: d.country
            },
            id: d.id
  				};
  			});
  			
  			var geoSet = {
		    	"type": "FeatureCollection",
  		  		"features": dataSet
  			}; 
  			



				// ----------------------- CROSSFILTER----------------------		
				var cdata = crossfilter(dataSet),
		    all = cdata.groupAll(),
		    year = cdata.dimension(function(d) {return d.properties.year;}),
		    yearGroup = year.group(function(d) {return Math.floor(d);}),
		    country = cdata.dimension(function(d) {return d.properties.country;}),
		    countryGroup = country.group(),
		    type = cdata.dimension(function(d) {return d.properties.type.split(/[0-9]|-|\(|\?|\~|\,|\<|\ /)[0];}),
		    /*
		    typeMassAmountGroup = type.group().reduce(
		    		// callback for when data is added to the current filter results 
		    		function (p, v) {
		    				++p.amount;
		    				p.mass += v.properties.mass;
		    				p.radius += radius(v.properties.mass);
		    				console.log("+Sum: ", p.amount, " Mass: ", p.mass, " Radius: ", p.radius);
		    				return p;
		    		},
		    		// callback for when data is removed from the current filter results 
		    		function (p, v) {
		    				--p.amount;
		    				p.mass -= v.properties.mass;
		    				p.radius -= radius(v.properties.mass);
		    				console.log("-Sum: ", p.amount, " Mass: ", p.mass, " Radius: ", p.radius);
		    				return p;
		    		},
		    		// initialize p 
		    		function () {
		    				return {amount: 0, mass: 0, radius: 0};
		    		}
		    ),*/
		    typeGroup = type.group().reduceSum(function(d) {
		    		if(d.properties.mass < 0.0)
		    				return 0;
		    		return d.properties.mass;
		    }),
		    validFoundGroup = year.group().reduceSum(function(d) {
		    		if((d.properties.valid == "Valid") && (d.properties.fall == "Found") && (d.properties.mass > 0.0))
		    				return d.properties.mass;
		    		return 0;
		    }),
		    validFellGroup = year.group().reduceSum(function(d) {
		    		if((d.properties.valid == "Valid") && (d.properties.fall == "Fell") && (d.properties.mass > 0.0))
		    				return d.properties.mass;
		    		return 0;
		    }),
		    relictFoundGroup = year.group().reduceSum(function(d) {
		    		if((d.properties.valid == "Relict") && (d.properties.fall == "Found") && (d.properties.mass > 0.0))
		    				return d.properties.mass;
		    		return 0;
		    }),
		    relictFellGroup = year.group().reduceSum(function(d) {
		    		if((d.properties.valid == "Relict") && (d.properties.fall == "Fell") && (d.properties.mass > 0.0))
		    				return d.properties.mass;
		    		return 0;
		    });
		    
		    
		    
				// ----------------------- QUANTIDADE por ANO------------------------
				var w1 = 750, h1 = 300, w2 = 230, h2 = 3000,
						yearChartBarMin = d3.min(dataSet, function(d) { return d.properties.year; }) - 5,
						yearChartBarMax = d3.max(dataSet, function(d) { return d.properties.year; }) + 5,
						yearChartBarQMax = Math.floor(yearGroup.top(1)[0].value / h1);
		    
				yearChart
	  			    .width(w1)
	  			    .height(h1)
	  			    .margins({top: 10, right: 20, bottom: 30, left: 30})
	  			    .dimension(year)
	  			    .group(yearGroup)
	  			    .x(d3.scale.linear().domain([yearChartBarMin, yearChartBarMax]))
	  			    .round(dc.round.floor)
	  			    .alwaysUseRounding(true)
	  			    .xUnits(function(){
	  			    		return 90;
	  			    })
	  			    .elasticX(true)
	  			    .elasticY(true)
	  			    //.y(d3.scale.linear().domain([-8,1800]))
	  			    //.yAxisPadding(yearChartBarQMax)
	  			    .xAxisLabel('Anos')
	  			    .yAxisLabel('Quantidade');
	  		yearChart.xAxis().tickFormat(d3.format('d'));
	  		yearChart.yAxis().tickFormat(d3.format('d'));//.ticks(10);
	  		
      
				// ----------------------- QUANTIDADE por PAIS------------------------
				var colorSize = countryGroup.top(1)[0].value;
				countryChart
	  			    .width(w2)
	  			    .height(h2)
	  			    .margins({top: 10, right: 20, bottom: 30, left: 40})
	  			    .dimension(country)
	  			    .group(countryGroup)
	  			    .colors(colorbrewer.RdBu[4])
	  			    .colorDomain([0, colorSize])
	  			    .colorAccessor(function(d, i){return d.value;})
	  			    .label(function (d) {
	  			    		return d.key;
	  			    })
	  			    .title(function (d) {
	  			    		return d.value;
	  			    })
	  			    .elasticX(true)
	  			    //.xAxisLabel('Quantidade')
	  			    //.yAxisLabel('País')
	  			    .xAxis().ticks(3).tickFormat(d3.format('d'));
	  			    
	  		
      
				// ----------------------- MASSA por MATERIAL------------------------
				var colorSize = typeGroup.top(1)[0].value;
				typeChart
	  			    .width(w2)
	  			    .height(1700)
	  			    .margins({top: 10, right: 20, bottom: 30, left: 40})
	  			    .dimension(type)
	  			    .group(typeGroup)
	  			    .colors(colorbrewer.RdBu[4])
	  			    .colorDomain([0, colorSize])
	  			    .colorAccessor(function(d, i){return d.value;})
	  			    .label(function (d) {
	  			    		return d.key;
	  			    })
	  			    .title(function (d) {
	  			    		return d.value;
	  			    })
	  			    .elasticX(true)
	  			    //.xAxisLabel('Massa')
	  			    //.yAxisLabel('Material')
	  			    .xAxis().ticks(2);
			    

				// ----------------------- MASSA por ANO (4 tipos)----------
				// Achado e valido, caido e valido, achado e relíquia, caido e relíquia
				massChart
	  			    //.renderArea(true)
	  			    .width(w1)
	  			    .height(h1)
	  			    .transitionDuration(1000)
	  			    .margins({top: 10, right: 20, bottom: 30, left: 60})
	  			    .dimension(year)
	  			    .mouseZoomable(true)
	  			    //Specify a range chart to link the brush extent of the range with the zoom focue of the current chart.
	  			    .rangeChart(yearChart)
	  			    .x(d3.scale.linear().domain([yearChartBarMin, yearChartBarMax]))
	  			    .round(dc.round.floor)
	  			    //.alwaysUseRounding(true)
	  			    .xUnits(function(){
	  			    		return 90;
	  			    })
	  			    .elasticY(true)
	  			    .renderHorizontalGridLines(true)
	  			    .legend(dc.legend().x(w1 - 150).y(10).itemHeight(13).gap(5))
	  			    .brushOn(false)
	  			    .xAxisLabel('Anos')
	  			    .yAxisLabel('Massa')
        // Add the base layer of the stack with group. The second parameter specifies a series name for use in the legend
        // The `.valueAccessor` will be used for the base layer
	  			    .compose([
											dc.lineChart(massChart)
													.dimension(year)
													.brushOn(false)
													.colors(d3.scale.ordinal().range(['red','blue','green','yellow']))
													.group(validFoundGroup, "Válido e Achado")
													.valueAccessor(function (d) {
	  				                          return d.value;
	  				                      })
													.title(function(d){
	  				                          return "Válido e Achado" + d.value;
	  				                      }),
											dc.lineChart(massChart)
													.dimension(year)
													.brushOn(false)
													.group(validFellGroup,  "Válido e Caído")
													.colorAccessor(function(d,i){return 1;})
													.colors(d3.scale.ordinal().range(['blue','red','green','yellow']))
													.valueAccessor(function (d) {
	  				                          return d.value;
	  				                      })
													.title(function(d){
	  				                          return "Válido e Caído" + d.value;
	  				                      }),
											dc.lineChart(massChart)
													.dimension(year)
													.brushOn(false)
													.colorAccessor(function(d,i){return 2;})
													.colors(d3.scale.ordinal().range(['green','blue','red','yellow']))
													.group(relictFellGroup, "Relíquia e Achado")
													.valueAccessor(function (d) {
	  				                          return d.value;
	  				                      })
													.title(function(d){
	  				                          return "Relíquia e Achado" + d.value;
	  				                      }),
											dc.lineChart(massChart)
													.dimension(year)
													.brushOn(false)
													.colorAccessor(function(d,i){return 2;})
													.colors(d3.scale.ordinal().range(['yellow','green','blue','red']))
													.group(relictFellGroup, "Relíquia e Caído")
													.valueAccessor(function (d) {
	  				                          return d.value;
	  				                      })
													.title(function(d){
	  				                          return "Relíquia e Caído" + d.value;
	  				                      })
				]);
	  		massChart.xAxis().tickFormat(d3.format('d'));
	  		
	  		
	  		
	  		/*
	  		
				// ----------------------- TIPO por MASSA/QUANTIDADE--------
    typeChart
        .width(990) // (optional) define chart width, :default = 200
        .height(250)  // (optional) define chart height, :default = 200
        .transitionDuration(100) // (optional) define chart transition duration, :default = 750
        .margins({top: 10, right: 50, bottom: 10, left: 60})
        .dimension(type)
        //Bubble chart expect the groups are reduced to multiple values which would then be used
        //to generate x, y, and radius for each key (bubble) in the group
        .group(typeMassAmountGroup)
        .colors(colorbrewer.RdYlGn[9]) // (optional) define color function or array for bubbles
        .colorDomain([0, 120000]) //(optional) define color domain to match your data domain if you want to bind data or color
        //##### Accessors
        //Accessor functions are applied to each value returned by the grouping
        //
        // * `.colorAccessor` The returned value will be mapped to an internal scale to determine a fill color
        // * `.keyAccessor` Identifies the `X` value that will be applied against the `.x()` to identify pixel location
        // * `.valueAccessor` Identifies the `Y` value that will be applied agains the `.y()` to identify pixel location
        // * `.radiusValueAccessor` Identifies the value that will be applied agains the `.r()` determine radius size, by default this maps linearly to [0,100]
        .colorAccessor(function (d) {
            return d.value.amount;
        })
        .keyAccessor(function (p) {
            return p.value.amount;
        })
        .valueAccessor(function (p) {
            return p.value.mass;
        })
        .radiusValueAccessor(function (p) {
            return p.value.mass;
        })
        .maxBubbleRelativeSize(0.1)
        .x(d3.scale.linear().domain([-5, 15]))
        .y(d3.scale.linear().domain([0, 120000]))
        .r(d3.scale.linear().domain([0, 15]))
        //##### Elastic Scaling
        //`.elasticX` and `.elasticX` determine whether the chart should rescale each axis to fit data.
        //The `.yAxisPadding` and `.xAxisPadding` add padding to data above and below their max values in the same unit domains as the Accessors.
        //.elasticY(true)
        //.elasticX(true)
        .renderHorizontalGridLines(true) // (optional) render horizontal grid lines, :default=false
        .renderVerticalGridLines(true) // (optional) render vertical grid lines, :default=false
        .xAxisLabel('Quantidade') // (optional) render an axis label below the x axis
        .yAxisLabel('Massa') // (optional) render a vertical axis lable left of the y axis
        //#### Labels and  Titles
        //Labels are displaed on the chart for each bubble. Titles displayed on mouseover.
        .renderLabel(true) // (optional) whether chart should render labels, :default = true
        .label(function (p) {
            return p.key;
        })
        .renderTitle(true) // (optional) whether chart should render titles, :default = false
        .title(function (p) {
            return [p.key,
                   "Llalala: "]
                   .join("\n");
        });
        //#### Customize Axis
        //Set a custom tick format. Note `.yAxis()` returns an axis object, so any additional method chaining applies to the axis, not the chart.
	  		typeChart.xAxis().tickFormat(d3.format('d')).ticks(5);
	  			    */
				dc.renderAll();
	
			
				var markers = L.markerClusterGroup({maxClusterRadius: 80, disableClusteringAtZoom:6});
				/* ----------------------- MAPA------------------------*/
				//mandando desenhar os pontos
				var marker = L.geoJson(geoSet, {
					onEachFeature: onEachFeature,

					pointToLayer: function (feature, latlng) {
						return L.circleMarker(latlng, {
							radius: radius(feature.properties.mass),
							fillColor: "blue",
							color: "#000",
							weight: 1,
							opacity: 1,
							fillOpacity: 0.8
						});
					}
				});//.addTo(map);

				markers.addLayer(marker);

				map.addLayer(markers);
		});
  	

	</script>
</body>

</html> 